(function ($) {
    "use strict";
    var NOT_LOAD = -1,
        LOADING = 0,
        LOADED = 1,

        lib_state = NOT_LOAD,
        map_stack =  {
            maps: [],
            counter: 0
        },

        marker_stack = {
            markers: [],
            counter: 0
        },

        /** Hàng đợi chia sẻ */
        global_queue = {
            functions: [],
            counter: 0
        };


    var GMap = function () {

    };

    /**
     * Lấy một phần tử Map từ danh sách map toàn cục
     * @param key
     * @return {*}
     */
    GMap.get = function (key) {
        if (map_stack.maps[key] !== undefined) {
            return map_stack.maps[key];
        } else {
            return null;
        }
    };

    GMap.del = function (key) {
        if (map_stack.maps[key] !== undefined) {
            delete  map_stack.maps[key];
            map_stack.counter--;
        }
    };

    GMap.get_marker = function (key) {
        if (key < marker_stack.counter) {
            return marker_stack.markers[key];
        }
        return null;
    };



    GMap.queue = function (func) {
        if (lib_state === LOADED) {
            func();
        } else {
            global_queue.counter++;
            global_queue.functions.push(func);
        }
    };

    /**
     * Thực hiện load google maps library, đặt hàm vào hàng đợi để thực thi sau khi load xong lib
     * @param func
     */
    GMap.load = function (func) {
        if (func) {
            GMap.queue(func);
        }

        if (lib_state === NOT_LOAD) {
            var api_url = "http://maps.googleapis.com/maps/api/js?key=" +
                GMap.settings.api_key + "&sensor=false&callback=" +
                GMap.settings.callback_function_name,
                script_html = '<script type="text/javascript" src="' + api_url + '"></script>', $head = $('head');

            // DOM chưa hoàn tất
            if ($head.length === 0) {
                $(function () {
                    $('head').append(script_html);
                });
            } else {
                $head.append(script_html);
            }

            lib_state = LOADING;

        }
    };

    GMap.coordinate = function (str, p2) {
        if (typeof  str === 'object') {
            return str;
        }

        if (!window.google.maps.LatLng) {
            console.log('ERROR: google maps lib is not loaded!');
            return null;
        }

        var result = new window.google.maps.LatLng(0, 0);

        if (typeof str === 'string') {
            str = str.replace(/^[\.\-]?[^\d\.\-]+/, "");
            var elements = str.split(',');
            if (elements[0] !== undefined && elements [1] !== undefined) {
                result = new google.maps.LatLng(parseFloat(elements[0]), parseFloat(elements[1]));
            }
        } else {
            result = new google.maps.LatLng(str, p2);
        }

        return result;
    };

    /**
     * Tạo mới một map và thêm vào stack
     * @param options
     * @return {number} key của map mới tạo ra
     */
    GMap.make_map = function (options) {
        var map,
            key = map_stack.counter;
        GMap.load(function () {
            options = $.extend({}, GMap.default_map, options);
            var element = $(options.element).get(0);

            options.center = GMap.coordinate(options.center);
            map = new google.maps.Map(element, options);

            map_stack.maps.push(map);
            map_stack.counter++;
        });

        return key;
    };

    GMap.listen = function (map, event, callback) {
        GMap.queue(function () {
            if (typeof map === "number") {
                map = GMap.get(map);
            }
            google.maps.event.addListener(map, event, function (e) {
                callback.call(this, e);
            });
        });
    };

    /**
     * Tạo ra một Marker và thêm vào map (được chỉ định trong đối số options.map)
     * @param options  .map: map | map_id
     * @return {*}
     */
    GMap.make_maker = function (options) {
        var marker,
            key = marker_stack.counter;
        options = $.extend({}, GMap.default_maker, options);
        if (options.map === undefined) {
            console.log('Can not create marker without map');
            return null;
        }

        GMap.queue(function () {
            if (typeof options.map === "number") {
                options.map = GMap.get(options.map);
            }

            if (typeof options.position === "string") {
                options.position = GMap.coordinate(options.position);
            }

            marker = new google.maps.Marker(options);
            marker_stack.markers.push(marker);
            marker_stack.counter++;
        });

        return key;

    };

    /**
     * Các giá trj mặc định cấu hình google maps lib
     * @type {{callback_function_name: string, api_key: string, element: string}}
     */
    GMap.settings = {
        callback_function_name: '__gmaps_load_success',
        api_key: 'AIzaSyAyEXgNgC32_IhPQqEyDohMOZou65Ee6gY',
    };

    GMap.default_map = {
        element: '#map-canvas',
        center: "10.031977,105.771036",
        zoom: 16,
        mapTypeId: 'roadmap'
    };

    GMap.default_maker = {
        position: GMap.default_map.center,
        draggable: false
    };

    /**
     * Callback được gọi khi load xong google maps lib
     */
    window[GMap.settings.callback_function_name] = function () {
        lib_state = LOADED;
        for (var i = 0; i < global_queue.counter; i++) {
            global_queue.functions[i]();
        }
    };

    window.GMap = GMap;
}(window.jQuery));